package com.sse.util;


/**
 * Clase de utilidad para el manejo de tramas.
 * 
 * 
 * ORDEN DE LA TRAMA DEL MENSAJE 
 * | RFID | CASAID | SENSORID | TIPOSENSOR | EVENTOID |
 * 
 * @author Jean Paul Manjarres Correal
 * 
 */
public class TramaUtil {

	// Cantidad de bits que se toman para cada elemento.

	public static final int bitsRFID = 8;
	public static final int bitsTipoSensor = 3;
	public static final int bitsEventoId = 3;
	public static final int bitsSensorId = 10;
	public static final int bitsCasaId = 10;

	// CONSTANTES CALCULADAS POR EL COMPILADOR, NO MODIFICAR
	public static final int bitDespEventoId = 0;
	public static final int bitDespTipoSensor = bitDespEventoId + bitsEventoId;
	public static final int bitDespSensorId = bitDespTipoSensor
			+ bitDespTipoSensor;
	public static final int bitDespCasaId = bitDespSensorId + bitsSensorId;
	public static final int bitDespRFID = bitDespCasaId + bitsCasaId;

	
	//CONSTANTES QUE DEFINEN LA CANTIDAD MAXIMA DE ELEMENTOS POR TIPO
	/** Cantidad maxima de valores para casas */
	public static final long MAX_CASA_ID = (long) Math.pow(2.0, bitsCasaId);

	/** Cantidad maxima de valores para sensor */
	public static final long MAX_SENSOR_ID = (long) Math.pow(2.0, bitsSensorId);

	/** Cantidad maxima de valores para evento */
	public static final long MAX_EVENTO_ID = (long) Math.pow(2.0, bitsEventoId);

	/** Cantidad maxima de valores para sensor */
	public static final long MAX_TIPO_SENSOR = (long) Math.pow(2.0,
			bitsTipoSensor);

	/** Cantidad maxima de valores para rfId */
	public static final long MAX_RFID = (long) Math.pow(2.0, bitsRFID);

	
	
	// CONSTANTES QUE DEFINEN LAS MASCARAS PARA LA INFORMACION. 
	
	/** Mascara para el valor casa */
	public static final long mascaraCasa = (MAX_CASA_ID - 1) << bitDespCasaId;

	/** Mascara para el valor sensor */
	public static final long mascaraSensor = (MAX_SENSOR_ID - 1) << bitDespSensorId;

	/** Mascara para el valor evento */
	public static final long mascaraEvento = (MAX_EVENTO_ID - 1) << bitDespEventoId;

	/** Mascara para el valor tiposensor */
	public static final long mascaraTipoSensor = (MAX_TIPO_SENSOR - 1) << bitDespTipoSensor;

	/** Mascara para el valor rfid */
	public static final long mascaraRFID = (MAX_RFID - 1) << bitDespRFID;

	
	
	/**
	 * Convierte los valores a enviar en una trama.
	 * 
	 * @param casaId
	 * @param sensorId
	 * @param eventoId
	 * @param tipoSensor
	 * @param rfid
	 * @return
	 */
	public static long convertirValoresATrama(long casaId, long sensorId,
			long eventoId, long tipoSensor, long rfid) {

		long trama = (casaId << bitDespCasaId) | (sensorId << bitDespSensorId)
				| (eventoId << bitDespEventoId)
				| (tipoSensor << bitDespTipoSensor) | (rfid << bitDespRFID);
		return trama;
	}

	/**
	 * Obtiene el identificador de casa con base en una trama.
	 * 
	 * @param trama
	 * @return Identficador de la casa
	 */
	public static long getCasaId(long trama) {
		return ((trama & mascaraCasa) >> bitDespCasaId);
	}

	/**
	 * Obtiene el identificador de casa con base en una trama.
	 * 
	 * @param trama
	 * @return Identficador de la casa
	 */
	public static long getSensorId(long trama) {
		return ((trama & mascaraSensor) >> bitDespSensorId);
	}

	/**
	 * Obtiene el identificador de evento con base en una trama.
	 * 
	 * @param trama
	 * @return Identficador del evento
	 */
	public static long getEventoId(long trama) {
		return ((trama & mascaraEvento) >> bitDespEventoId);
	}

	/**
	 * Obtiene el identificador de tipo de sensor con base en una trama.
	 * 
	 * @param trama
	 * @return Identficador del tipo de sensor
	 */
	public static long getTipoSensor(long trama) {
		return ((trama & mascaraTipoSensor) >> bitDespTipoSensor);
	}

	/**
	 * Obtiene el identificador del rfid con base en una trama.
	 * 
	 * @param trama
	 * @return Identficador del rfid
	 */
	public static long getRFID(long trama) {
		return ((trama & mascaraRFID) >> bitDespRFID);
	}

	

	
	
	public static void main(String[] args) {

		// TEST:
		// A partir de unos identificadores se genera la trama y
		// luego vuelven a generarse los identificadores.

		// long casa = 40L;
		// long sensor = 12L;
		// long evento = 6L;
		// long tiposensor = 4L;
		// long rfid = 21;

		long casa = 510L;
		long sensor = 63L;
		long evento = 6L;
		long tiposensor = 4L;
		long rfid = 21;

		long trama = TramaUtil.convertirValoresATrama(casa, sensor, evento,
				tiposensor, rfid);

		System.out.println("Trama: " + trama);
		System.out.println("Casa: " + TramaUtil.getCasaId(trama));
		System.out.println("Sensor: " + TramaUtil.getSensorId(trama));
		System.out.println("Evento: " + TramaUtil.getEventoId(trama));
		System.out.println("TipoSensor: " + TramaUtil.getTipoSensor(trama));
		System.out.println("RFID: " + TramaUtil.getRFID(trama));

		byte[] array = ByteUtil.longToByteA(trama);
		System.out.println("Byte Array: "+array);
		System.out.println("Long: "+ByteUtil.byteAToLong(array));
		
//		long date = System.currentTimeMillis();

	}

}
